package com.haifeng.sbtx.auth.service.impl;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.Charsets;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.security.oauth2.common.util.RandomValueStringGenerator;
import org.springframework.security.oauth2.common.util.SerializationUtils;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.code.RandomValueAuthorizationCodeServices;
import org.springframework.stereotype.Component;

import java.util.Objects;

/**
 * <p>
 *  自定义授权码Redis存储
 * </p>
 *
 * @author: Haifeng
 * @date: 2019-12-15
 */
@Slf4j
@Component
public class CustomRedisAuthorizationCodeServices extends RandomValueAuthorizationCodeServices {

    private static final String AUTH_CODE_KEY = "authentication_code:";
    private Integer codeLength = 25;
    private Long time = 300L;
    private RandomValueStringGenerator generator;
    private RedisConnectionFactory connectionFactory;

    public CustomRedisAuthorizationCodeServices(RedisConnectionFactory connectionFactory) {
        this.connectionFactory = connectionFactory;
        this.generator = new RandomValueStringGenerator(codeLength);
    }

    private RedisConnection getConnection() {
        return connectionFactory.getConnection();
    }

    @Override
    public String createAuthorizationCode(OAuth2Authentication authentication) {
        String code = this.generator.generate();
        store(AUTH_CODE_KEY + code, authentication);
        return code;
    }

    @Override
    protected void store(String code, OAuth2Authentication authentication) {
        RedisConnection conn = getConnection();
        try {
            conn.set(code.getBytes(Charsets.UTF_8), SerializationUtils.serialize(authentication));
            conn.expire(code.getBytes(Charsets.UTF_8), time);
        } catch (Exception e) {
            conn.close();
        }

    }

    @Override
    protected OAuth2Authentication remove(String code) {
        RedisConnection conn = getConnection();
        try {
            OAuth2Authentication authentication = null;
            try {
                if (conn.exists((AUTH_CODE_KEY + code).getBytes(Charsets.UTF_8))){
                    authentication = SerializationUtils
                            .deserialize(Objects.requireNonNull(conn.get((AUTH_CODE_KEY + code).getBytes(Charsets.UTF_8))));
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            if (authentication != null) {
                conn.del((AUTH_CODE_KEY + code).getBytes(Charsets.UTF_8));
            }
            return authentication;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            conn.close();
        }
        return null;
    }
}
